//核心！异常必须处理，没处理就交给JVM了，最终的处理都是使用try-catch
//受查异常多了一个选择，可以throws声明，可以try-catch

public class LogIn {
    private String userName = "admin";
    private String password = "123456";

    public void loginInfo(String userName,String password) throws UserNameException, PasswordException{ //异常的声明
        if(!this.userName.equals(userName)){
            throw new UserNameException("用户名错误！" + userName); //异常的抛出
           //throw必须写在方法体内部。异常一旦抛出，其后的代码就不会执行
        }
        if(!this.password.equals(password)){
            throw new PasswordException("密码错误！" + password);
        }
        System.out.println("登录成功");
    }

    public static void main(String[] args) {
        try{
            //可能会发生异常的代码
            LogIn login = new LogIn();
            login.loginInfo("admin","123456");
            //try块内抛出异常位置之后的代码将不会被执行
        }catch (UserNameException e){ //对捕获到的异常进行处理
            /* 如果try中的代码抛出异常了，catch捕获的异常类型与try中抛出的异常类型一致时；或者catch中是try抛出异常的父类时，就会被捕获到。
            对异常就可以正常处理，处理完成后，跳出try-catch结构，继续执行后序代码 */
            e.printStackTrace();
        }catch (PasswordException e){
            e.printStackTrace();
        }finally {
            //此处的语句无论是否发生异常，都会被执行
            System.out.println("finally被执行了...");
        }
        //后序代码
        //如果没有抛出异常，或者异常被捕获处理了，这里的代码也会执行
        System.out.println("后序代码被执行了...");
    }
}


//异常处理流程总结：
//程序先执行try中的代码
//如果try中的代码出现异常，就会结束try中的代码，看和catch中的异常类型是否匹配
//如果找到匹配的异常类型，就会执行catch中的代码
//如果没有找到匹配的异常类型，就会将异常向上传递到上层调用者
//无论是否找到匹配的异常类型，finally中的代码都会被执行到（在该方法结束之前执行）
//如果上层调用者也没有处理得了异常，就继续向上传递
//一直到main方法也没有合适的代码处理异常，就会交给JVM来进行处理，此时程序就会异常终止

//自定义异常通常会继承自Exception或者RuntimeException
//继承自Exception的异常默认是受查异常
//继承自RuntimeException的异常默认是运行时异常